package com.jijuxie.house.controller;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.Date;
import java.util.ArrayList;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jijuxie.common.core.R;
import com.jijuxie.common.domain.Coordinate;
import com.jijuxie.common.exception.ServiceException;
import com.jijuxie.common.service.MapService;
import com.jijuxie.common.service.FileService;
import com.jijuxie.house.domain.HouseInfo;
import com.jijuxie.house.domain.HouseImage;
import com.jijuxie.house.domain.dto.AuditHouseDTO;
import com.jijuxie.house.domain.dto.ChangeStatusDTO;
import com.jijuxie.house.domain.dto.HouseSearchDTO;
import com.jijuxie.house.domain.vo.HouseListVO;
import com.jijuxie.house.domain.vo.HouseMapVO;
import com.jijuxie.house.domain.vo.HouseCollectVO;
import com.jijuxie.house.service.IHouseService;
import com.jijuxie.house.service.IHouseImageService;
import com.jijuxie.house.domain.UserHouseCollect;
import com.jijuxie.house.mapper.UserHouseCollectMapper;

import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.stp.StpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@RestController
@RequestMapping("/house")
public class HouseController {

    private static final Logger log = LoggerFactory.getLogger(HouseController.class);

    @Autowired
    private IHouseService houseService;

    @Autowired
    private MapService mapService;

    @Autowired
    private UserHouseCollectMapper userHouseCollectMapper;

    @Autowired
    private FileService fileService;
    
    @Autowired
    private IHouseImageService houseImageService;

    /**
     * 获取房源列表
     */
    @GetMapping("/list")
    public R<Page<HouseInfo>> list(
            @RequestParam(defaultValue = "1") Integer current,
            @RequestParam(defaultValue = "10") Integer size,
            @RequestParam(required = false) BigDecimal minPrice,
            @RequestParam(required = false) BigDecimal maxPrice,
            @RequestParam(required = false) BigDecimal minArea,
            @RequestParam(required = false) BigDecimal maxArea,
            @RequestParam(required = false) String houseType,
            @RequestParam(required = false) Integer bedroom,
            @RequestParam(required = false) String sortField,
            @RequestParam(required = false) String sortOrder) {
        Page<HouseInfo> page = new Page<>(current, size);
        HouseInfo houseInfo = new HouseInfo();
        houseInfo.setHouseType(houseType);
        houseInfo.setBedroom(bedroom);
        return R.ok(houseService.selectHousePage(page, houseInfo, minPrice, maxPrice, minArea, maxArea, sortField, sortOrder));
    }

    /**
     * 获取房源详情
     */
    @GetMapping("/info/{houseId}")
    public R<HouseInfo> getInfo(@PathVariable Long houseId) {
        return R.ok(houseService.selectHouseById(houseId));
    }

    /**
     * 添加房源（包含图片上传）
     */
    @PostMapping(value = "/add", consumes = "multipart/form-data")
    public R<Map<String, Object>> addHouseWithImages(
            @RequestParam("title") String title,
            @RequestParam("houseType") String houseType,
            @RequestParam("propertyType") String propertyType,
            @RequestParam("province") String province,
            @RequestParam("city") String city,
            @RequestParam("district") String district,
            @RequestParam("community") String community,
            @RequestParam("address") String address,
            @RequestParam("layout") String layout,
            @RequestParam("area") String area,
            @RequestParam("floor") String floor,
            @RequestParam("direction") String direction,
            @RequestParam("decoration") String decoration,
            @RequestParam("buildYear") String buildYear,
            @RequestParam("price") BigDecimal price,
            @RequestParam("unitPrice") String unitPrice,
            @RequestParam("description") String description,
            @RequestParam("contactName") String contactName,
            @RequestParam("contactPhone") String contactPhone,
            @RequestParam(value = "lng", required = false) String lng,
            @RequestParam(value = "lat", required = false) String lat,
            @RequestParam("coverImage") MultipartFile coverImage,
            @RequestParam(value = "houseImages", required = false) List<MultipartFile> houseImages) {
        
        try {
            log.info("接收到添加房源请求: {}, 封面图大小: {}, 房源照片数量: {}", 
                    title, coverImage.getSize(), houseImages != null ? houseImages.size() : 0);
            log.info("接收到的经纬度参数: lng={}, lat={}", lng, lat);
            
            // 1. 先保存房源基本信息获取ID
            HouseInfo houseInfo = new HouseInfo();
            houseInfo.setTitle(title);
            houseInfo.setHouseType(houseType);
            houseInfo.setPropertyType(propertyType);
            houseInfo.setProvince(province);
            houseInfo.setCity(city);
            houseInfo.setDistrict(district);
            houseInfo.setAddress(address);
            // 处理Layout - 可能需要映射到bedroom、livingRoom和bathroom
            // 假设layout的格式为"X室X厅X卫"
            if (layout != null && !layout.isEmpty()) {
                try {
                    String[] parts = layout.split("[室厅卫]");
                    if (parts.length >= 1) {
                        houseInfo.setBedroom(Integer.parseInt(parts[0]));
                    }
                    if (parts.length >= 2) {
                        houseInfo.setLivingRoom(Integer.parseInt(parts[1]));
                    }
                    if (parts.length >= 3) {
                        houseInfo.setBathroom(Integer.parseInt(parts[2]));
                    }
                } catch (Exception e) {
                    log.warn("解析户型失败: {}", layout);
                }
            }
            
            houseInfo.setArea(new BigDecimal(area));
            try {
                houseInfo.setFloor(Integer.parseInt(floor));
            } catch (NumberFormatException e) {
                log.warn("楼层转换为整数失败: {}", floor);
            }
            // 方向使用orientation字段
            houseInfo.setOrientation(direction);
            houseInfo.setDecoration(decoration);
            houseInfo.setPrice(price);
            houseInfo.setPriceUnit(unitPrice);
            houseInfo.setDescription(description);
            // contactName和contactPhone可能需要存储在其他表中或其他字段
            // 可能需要设置发布者ID
        Long userId = StpUtil.getLoginIdAsLong();
            houseInfo.setPublisherId(userId);
            houseInfo.setStatus("0"); // 0表示待审核状态
            houseInfo.setCreateTime(LocalDateTime.now());
            houseInfo.setUpdateTime(LocalDateTime.now());
            houseInfo.setDelFlag("0"); // 0表示未删除
            
            // 优先使用前端传递的经纬度参数
            if (lng != null && !lng.isEmpty() && lat != null && !lat.isEmpty()) {
                try {
                    log.info("使用前端传递的经纬度参数: lng={}, lat={}", lng, lat);
                    houseInfo.setLng(new BigDecimal(lng));
                    houseInfo.setLat(new BigDecimal(lat));
                } catch (NumberFormatException e) {
                    log.error("前端传递的经纬度参数格式不正确: lng={}, lat={}", lng, lat, e);
                    // 经纬度格式错误，继续使用地址获取经纬度
                    getCoordinateFromAddress(houseInfo, province, city, district, address, community);
                }
                } else {
                // 如果前端未传递经纬度，则通过地址获取
                log.info("前端未传递经纬度参数，将通过地址获取");
                getCoordinateFromAddress(houseInfo, province, city, district, address, community);
        }

            // 2. 保存到数据库获取ID
        houseService.insertHouse(houseInfo);
            Long houseId = houseInfo.getHouseId();
            
            // 3. 保存封面图
            String coverImageUrl = fileService.saveHouseImage(coverImage, "house/CoverImage/" + houseId + "/");
            houseInfo.setCoverImage(coverImageUrl);
            
            // 保存封面图记录到house_image表
            HouseImage coverHouseImage = new HouseImage();
            coverHouseImage.setHouseId(houseId);
            coverHouseImage.setImageUrl(coverImageUrl);
            coverHouseImage.setImageType("1"); // 1表示封面图
            coverHouseImage.setUploadTime(LocalDateTime.now());
            coverHouseImage.setSort(0); // 封面图排序优先
            houseImageService.save(coverHouseImage);
            
            // 4. 更新封面图URL
            houseService.updateById(houseInfo);
            
            // 5. 保存房源照片
            List<String> imageUrls = new ArrayList<>();
            if (houseImages != null && !houseImages.isEmpty()) {
                String subDir = "house/ListingPhoto/" + houseId + "/";
                for (MultipartFile file : houseImages) {
                    if (!file.isEmpty()) {
                        try {
                            String imageUrl = fileService.saveHouseImage(file, subDir);
                            imageUrls.add(imageUrl);
                            
                            // 保存房源图片记录
                            HouseImage houseImage = new HouseImage();
                            houseImage.setHouseId(houseId);
                            houseImage.setImageUrl(imageUrl);
                            houseImage.setImageType("2"); // 2表示室内图
                            houseImage.setUploadTime(LocalDateTime.now());
                            houseImageService.save(houseImage);
                        } catch (Exception e) {
                            log.error("保存房源照片失败: ", e);
        }
                    }
                }
            }
            
            // 6. 返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("houseId", houseId);
            result.put("coverImage", coverImageUrl);
            result.put("imageUrls", imageUrls);
            
            return R.ok(result);
        } catch (Exception e) {
            log.error("添加房源失败: ", e);
            return R.fail("添加房源失败: " + e.getMessage());
        }
    }

    /**
     * 通过地址获取经纬度
     */
    private void getCoordinateFromAddress(HouseInfo houseInfo, String province, String city, String district, String address, String community) {
        try {
            // 构建完整地址
            String fullAddress = province + city + district + address;
            if (community != null && !community.isEmpty()) {
                fullAddress = fullAddress + " " + community;
            }
            
            log.info("开始通过地址获取经纬度: {}", fullAddress);
            Coordinate coordinate = mapService.geocoder(fullAddress);
            if (coordinate != null) {
                houseInfo.setLng(coordinate.getLng());
                houseInfo.setLat(coordinate.getLat());
                log.info("成功获取房源经纬度: {}, {}", coordinate.getLng(), coordinate.getLat());
            } else {
                log.warn("未能获取地址的经纬度，将使用默认值");
                // 使用默认经纬度（可以根据城市设置一个默认中心点）
                houseInfo.setLng(new BigDecimal("116.397428"));
                houseInfo.setLat(new BigDecimal("39.90923"));
            }
        } catch (Exception e) {
            log.error("获取经纬度失败", e);
            // 使用默认经纬度（不因为地理编码失败而影响房源添加）
            houseInfo.setLng(new BigDecimal("116.397428"));
            houseInfo.setLat(new BigDecimal("39.90923"));
        }
    }

    /**
     * 修改房源
     */
    @PutMapping
    @Transactional(rollbackFor = Exception.class)
    public R<Void> edit(@RequestBody HouseInfo houseInfo) {
        // 需要添加以下逻辑：

        // 1. 验证权限
        Long userId = StpUtil.getLoginIdAsLong();
        
        // 只有发布者或管理员可以修改
        HouseInfo original = houseService.getById(houseInfo.getHouseId());
        if (original == null) {
            return R.fail("房源不存在");
        }
        
        if (!userId.equals(original.getPublisherId()) && !StpUtil.hasRole("admin")) {
            return R.fail("无权修改此房源");
        }

        // 2. 如果地址发生了变化，更新经纬度
        boolean addressChanged = !original.getProvince().equals(houseInfo.getProvince()) ||
                                 !original.getCity().equals(houseInfo.getCity()) ||
                                 !original.getDistrict().equals(houseInfo.getDistrict()) ||
                                 (original.getAddress() == null && houseInfo.getAddress() != null) ||
                                 (original.getAddress() != null && !original.getAddress().equals(houseInfo.getAddress()));
        
        if (addressChanged) {
            try {
                String fullAddress = houseInfo.getProvince() + houseInfo.getCity() + 
                                    houseInfo.getDistrict() + houseInfo.getAddress();
                
                log.info("地址已变更，重新获取经纬度: {}", fullAddress);
            Coordinate coordinate = mapService.geocoder(fullAddress);
                
                if (coordinate != null) {
            houseInfo.setLng(coordinate.getLng());
            houseInfo.setLat(coordinate.getLat());
                    log.info("成功获取房源新经纬度: {}, {}", coordinate.getLng(), coordinate.getLat());
                }
            } catch (Exception e) {
                log.error("更新经纬度失败", e);
                // 保留原经纬度
                houseInfo.setLng(original.getLng());
                houseInfo.setLat(original.getLat());
            }
        } else {
            // 地址未变更，保留原经纬度
            houseInfo.setLng(original.getLng());
            houseInfo.setLat(original.getLat());
        }

        // 3. 执行更新
        houseInfo.setUpdateTime(LocalDateTime.now());
        houseInfo.setUpdateBy(StpUtil.getLoginIdAsString());
        boolean success = houseService.updateById(houseInfo);
        
        if (success) {
        return R.ok();
        } else {
            return R.fail("修改失败");
        }
    }

    /**
     * 删除房源
     */
    @DeleteMapping("/{houseId}")
    public R<Void> remove(@PathVariable Long houseId) {
        houseService.deleteHouse(houseId);
        return R.ok();
    }

    /**
     * 审核房源
     */
    @PutMapping("/audit/{houseId}")
    @SaCheckRole("admin")  // 需要管理员权限
    public R<Void> audit(@PathVariable Long houseId, @RequestParam String status) {
        houseService.auditHouse(houseId, status, StpUtil.getLoginIdAsLong());
        return R.ok();
    }

    /**
     * 上架/下架房源
     */
    @PutMapping("/changeStatus")
    public R<Void> changeStatus(@RequestParam Long houseId, @RequestParam String status) {
        // 只允许修改为下架或成交状态
        if (!"2".equals(status) && !"3".equals(status)) {
            throw new ServiceException("状态值不正确");
        }
        houseService.changeStatus(houseId, status);
        return R.ok();
    }

    /**
     * 搜索房源
     */
    @PostMapping("/search")
    public R<Page<HouseInfo>> search(
            @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
            @RequestBody HouseSearchDTO searchDTO) {
        Page<HouseInfo> page = houseService.searchHousePage(new Page<>(pageNum, pageSize), searchDTO);
        return R.ok(page);
    }

    /**
     * 检查房源是否已收藏
     */
    @GetMapping("/collect/check/{houseId}")
    public R<Boolean> checkCollect(@PathVariable Long houseId) {
        // 参数验证，防止前端传递undefined
        if (houseId == null) {
            log.warn("检查收藏状态时接收到无效的房源ID: null");
            return R.ok(false);
        }
        
        Boolean isCollected = houseService.checkCollect(houseId, StpUtil.getLoginIdAsLong());
        return R.ok(isCollected);
    }

    /**
     * 获取用户收藏总数
     */
    @GetMapping("/collect/count")
    public R<Integer> getUserCollectCount() {
        Integer count = houseService.getUserCollectCount(StpUtil.getLoginIdAsLong());
        return R.ok(count);
    }

    /**
     * 收藏房源
     */
    @PostMapping("/collect/{houseId}")
    @Transactional(rollbackFor = Exception.class)
    public R<Map<String, Object>> collect(@PathVariable Long houseId) {
        try {
            Long userId = StpUtil.getLoginIdAsLong();
            log.info("用户[{}]收藏房源[{}]", userId, houseId);
            
            // 检查房源是否存在
            HouseInfo house = houseService.getById(houseId);
            if (house == null) {
                log.warn("房源[{}]不存在", houseId);
                return R.fail("房源不存在");
            }
            
            // 检查房源状态
            if (!"1".equals(house.getStatus())) {
                log.warn("房源[{}]未上架，状态为[{}]", houseId, house.getStatus());
                return R.fail("房源未上架，无法收藏");
            }
            
            // 检查是否已收藏
            QueryWrapper<UserHouseCollect> wrapper = new QueryWrapper<>();
            wrapper.eq("house_id", houseId)
                    .eq("user_id", userId)
                    .eq("status", "1");
            UserHouseCollect existingCollect = userHouseCollectMapper.selectOne(wrapper);
            if (existingCollect != null) {
                log.info("用户[{}]已收藏房源[{}]", userId, houseId);
                
                // 返回已有的收藏信息
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("collectTime", existingCollect.getCollectTime());
                resultMap.put("isCollected", true);
                
                return R.ok(resultMap);
            }
            
            // 检查是否曾经收藏过但取消了
            wrapper = new QueryWrapper<>();
            wrapper.eq("house_id", houseId)
                   .eq("user_id", userId)
                   .eq("status", "0");
            existingCollect = userHouseCollectMapper.selectOne(wrapper);
            
            if (existingCollect != null) {
                // 更新已存在的记录
                existingCollect.setStatus("1");
                existingCollect.setCollectTime(LocalDateTime.now());
                existingCollect.setUpdateTime(LocalDateTime.now());
                
                int result = userHouseCollectMapper.updateById(existingCollect);
                log.info("用户[{}]更新房源[{}]收藏状态结果: {}", userId, houseId, result);
                
                if (result > 0) {
                    // 更新房源收藏数
                    boolean updateResult = houseService.lambdaUpdate()
                            .setSql("collect_count = collect_count + 1")
                            .eq(HouseInfo::getHouseId, houseId)
                            .update();
                    log.info("更新房源[{}]收藏数结果: {}", houseId, updateResult);
                    
                    // 返回收藏时间和状态
                    Map<String, Object> resultMap = new HashMap<>();
                    resultMap.put("collectTime", existingCollect.getCollectTime());
                    resultMap.put("isCollected", true);
                    
                    return R.ok(resultMap);
                } else {
                    log.error("用户[{}]更新房源[{}]收藏状态失败: 数据库更新返回0", userId, houseId);
                    return R.fail("收藏失败，请稍后重试");
                }
            }
            
            // 创建新收藏记录
            UserHouseCollect collect = new UserHouseCollect();
            collect.setUserId(userId);
            collect.setHouseId(houseId);
            collect.setCollectTime(LocalDateTime.now());
            collect.setCreateTime(LocalDateTime.now());
            collect.setUpdateTime(LocalDateTime.now());
            collect.setStatus("1"); // 1-已收藏
            
            try {
                // 保存收藏
                int result = userHouseCollectMapper.insert(collect);
                log.info("用户[{}]收藏房源[{}]结果: {}", userId, houseId, result);
                
                if (result > 0) {
                    // 更新房源收藏数
                    boolean updateResult = houseService.lambdaUpdate()
                            .setSql("collect_count = collect_count + 1")
                            .eq(HouseInfo::getHouseId, houseId)
                            .update();
                    log.info("更新房源[{}]收藏数结果: {}", houseId, updateResult);
                    
                    // 返回收藏时间和状态
                    Map<String, Object> resultMap = new HashMap<>();
                    resultMap.put("collectTime", collect.getCollectTime());
                    resultMap.put("isCollected", true);
                    
                    return R.ok(resultMap);
                } else {
                    log.error("用户[{}]收藏房源[{}]失败: 数据库插入返回0", userId, houseId);
                    return R.fail("收藏失败，请稍后重试");
                }
            } catch (Exception e) {
                // 处理可能的唯一约束冲突 - 防止并发情况
                log.warn("用户[{}]收藏房源[{}]时发生异常，可能是并发操作导致: {}", userId, houseId, e.getMessage());
                
                // 再次查询看是否已收藏成功
                wrapper = new QueryWrapper<>();
                wrapper.eq("house_id", houseId)
                       .eq("user_id", userId);
                existingCollect = userHouseCollectMapper.selectOne(wrapper);
                
                if (existingCollect != null) {
                    // 如果已存在记录但状态是取消，则更新状态
                    if ("0".equals(existingCollect.getStatus())) {
                        existingCollect.setStatus("1");
                        existingCollect.setCollectTime(LocalDateTime.now());
                        existingCollect.setUpdateTime(LocalDateTime.now());
                        userHouseCollectMapper.updateById(existingCollect);
                        
                        // 更新房源收藏数
                        houseService.lambdaUpdate()
                                .setSql("collect_count = collect_count + 1")
                                .eq(HouseInfo::getHouseId, houseId)
                                .update();
                    }
                    
                    // 返回收藏信息
                    Map<String, Object> resultMap = new HashMap<>();
                    resultMap.put("collectTime", existingCollect.getCollectTime());
                    resultMap.put("isCollected", "1".equals(existingCollect.getStatus()));
                    
                    return R.ok(resultMap);
                }
                
                // 如果还是失败，则抛出异常
                throw e;
            }
        } catch (Exception e) {
            log.error("收藏房源失败", e);
            return R.fail("系统繁忙，请稍后重试");
        }
    }

    /**
     * 取消收藏
     */
    @DeleteMapping("/collect/{houseId}")
    @Transactional(rollbackFor = Exception.class)
    public R<Map<String, Object>> cancelCollect(@PathVariable Long houseId) {
        try {
            Long userId = StpUtil.getLoginIdAsLong();
            
            // 检查房源是否存在
            HouseInfo house = houseService.getById(houseId);
            if (house == null) {
                return R.fail("房源不存在");
            }
            
            // 更新收藏状态为已取消
            UserHouseCollect collect = new UserHouseCollect();
            collect.setStatus("0");
            collect.setUpdateTime(LocalDateTime.now());
            
            // 更新收藏记录
            LambdaUpdateWrapper<UserHouseCollect> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(UserHouseCollect::getUserId, userId)
                   .eq(UserHouseCollect::getHouseId, houseId)
                   .eq(UserHouseCollect::getStatus, "1");
            
            int updated = userHouseCollectMapper.update(collect, wrapper);
            if (updated > 0) {
                // 更新房源收藏数
                houseService.lambdaUpdate()
                        .setSql("collect_count = GREATEST(collect_count - 1, 0)")
                        .eq(HouseInfo::getHouseId, houseId)
                        .update();
                
                // 获取更新后的收藏总数
                Integer total = userHouseCollectMapper.countUserCollects(userId);
                
                Map<String, Object> result = new HashMap<>();
                result.put("total", total);
                
                return R.ok(result);
            } else {
                return R.fail("取消收藏失败，请稍后重试");
            }
        } catch (Exception e) {
            log.error("取消收藏失败", e);
            return R.fail("系统繁忙，请稍后重试");
        }
    }

    /**
     * 获取收藏列表
     */
    @GetMapping("/collect/list")
    public R<Page<HouseCollectVO>> collectList(
            @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
            @RequestParam(value = "orderBy", defaultValue = "collectTime") String orderBy,
            @RequestParam(value = "orderDirection", defaultValue = "desc") String orderDirection) {
        try {
            Long userId = StpUtil.getLoginIdAsLong();
            log.info("获取用户[{}]收藏列表，参数：pageNum={}, pageSize={}, orderBy={}, orderDirection={}", 
                    userId, pageNum, pageSize, orderBy, orderDirection);
            
            // 获取总收藏数
            Integer total = userHouseCollectMapper.countUserCollects(userId);
            log.info("用户[{}]收藏总数：{}", userId, total);
            
            // 计算分页参数
            int offset = (pageNum - 1) * pageSize;
            int limit = pageSize;
            
            // 获取收藏列表（包含收藏时间）
            List<Map<String, Object>> housesMap = userHouseCollectMapper.selectCollectListWithTime(
                    userId, orderBy, orderDirection, offset, limit);
            log.info("查询到收藏列表数量：{}", housesMap != null ? housesMap.size() : 0);
            
            if (housesMap == null || housesMap.isEmpty()) {
                // 如果没有收藏记录，直接返回空结果
                Page<HouseCollectVO> result = new Page<>(pageNum, pageSize);
                result.setRecords(List.of());
                result.setTotal(total);
                return R.ok(result);
            }
            
            // 将 Map 转换为 HouseCollectVO
            List<HouseCollectVO> houses = housesMap.stream()
                    .map(map -> {
                        HouseCollectVO vo = new HouseCollectVO();
                        try {
                            // 手动设置关键字段，避免类型转换错误
                            if (map.get("house_id") != null) {
                                vo.setHouseId(Long.valueOf(map.get("house_id").toString()));
                            }
                            if (map.get("title") != null) {
                                vo.setTitle(map.get("title").toString());
                            }
                            if (map.get("description") != null) {
                                vo.setDescription(map.get("description").toString());
                            }
                            if (map.get("province") != null) {
                                vo.setProvince(map.get("province").toString());
                            }
                            if (map.get("city") != null) {
                                vo.setCity(map.get("city").toString());
                            }
                            if (map.get("district") != null) {
                                vo.setDistrict(map.get("district").toString());
                            }
                            if (map.get("address") != null) {
                                vo.setAddress(map.get("address").toString());
                            }
                            if (map.get("collect_time") != null) {
                                LocalDateTime collectTime = (LocalDateTime)map.get("collect_time");
                                vo.setCollectTime(collectTime);
                                // 设置字符串格式的时间，使用ISO格式
                                vo.setCollectTimeStr(collectTime.toString());
                            }
                            if (map.get("is_collected") != null) {
                                vo.setIsCollected(Integer.valueOf(map.get("is_collected").toString()) == 1);
                            }
                            if (map.get("price") != null) {
                                vo.setPrice(new BigDecimal(map.get("price").toString()));
                            }
                            if (map.get("area") != null) {
                                vo.setArea(new BigDecimal(map.get("area").toString()));
                            }
                            if (map.get("bedroom") != null) {
                                try {
                                    vo.setBedroom(Integer.valueOf(map.get("bedroom").toString()));
                                } catch (Exception e) {
                                    log.warn("卧室数转换失败: {}", map.get("bedroom"));
                                }
                            }
                            if (map.get("living_room") != null) {
                                try {
                                    vo.setLivingRoom(Integer.valueOf(map.get("living_room").toString()));
                                } catch (Exception e) {
                                    log.warn("客厅数转换失败: {}", map.get("living_room"));
                                }
                            }
                            if (map.get("bathroom") != null) {
                                try {
                                    vo.setBathroom(Integer.valueOf(map.get("bathroom").toString()));
                                } catch (Exception e) {
                                    log.warn("卫生间数转换失败: {}", map.get("bathroom"));
                                }
                            }
                            if (map.get("status") != null) {
                                vo.setStatus(map.get("status").toString());
                            }
                            if (map.get("cover_image") != null) {
                                vo.setCoverImage(map.get("cover_image").toString());
                            }
                        } catch (Exception e) {
                            log.error("属性转换错误", e);
                        }
                        return vo;
                    })
                    .collect(Collectors.toList());
            
            log.info("转换后的收藏列表数量：{}", houses.size());
            
            // 创建分页结果
            Page<HouseCollectVO> result = new Page<>(pageNum, pageSize);
            result.setRecords(houses);
            result.setTotal(total);
            
            return R.ok(result);
        } catch (Exception e) {
            log.error("获取收藏列表失败", e);
            return R.fail("系统繁忙，请稍后重试");
        }
    }

    /**
     * 获取地图房源信息
     */
    @GetMapping("/map/{houseId}")
    public R<HouseMapVO> getMapInfo(@PathVariable Long houseId) {
        return R.ok(houseService.selectMapInfo(houseId));
    }

    /**
     * 获取区域内房源
     */
    @GetMapping("/map/area")
    public R<List<HouseMapVO>> getAreaHouses(
            @RequestParam Double minLng,
            @RequestParam Double maxLng,
            @RequestParam Double minLat,
            @RequestParam Double maxLat) {
        return R.ok(houseService.selectAreaHouses(minLng, maxLng, minLat, maxLat));
    }

    /**
     * 查询已删除的房源列表
     */
    @GetMapping("/deleted")
    public R<Page<HouseInfo>> listDeleted(Page<HouseInfo> page, HouseInfo houseInfo) {
        return R.ok(houseService.selectDeletedHousePage(page, houseInfo));
    }

    /**
     * 恢复已删除的房源
     */
    @PutMapping("/restore/{houseId}")
    public R<Void> restore(@PathVariable Long houseId) {
        houseService.restoreHouse(houseId);
        return R.ok();
    }

    @PutMapping("/audit")
    public R<Void> auditHouse(@RequestBody @Validated AuditHouseDTO auditDTO) {
        houseService.auditHouse(auditDTO.getHouseId(), auditDTO.getStatus(), StpUtil.getLoginIdAsLong());
        return R.ok();
    }

    /**
     * 修改房源状态 状态流转： 1. 已上架 -> 下架：直接修改为下架状态 2. 已下架 -> 上架：修改为待审核状态，需要重新审核 3.
     * 成交功能暂未开放
     */
    @PutMapping("/status")
    public R<Void> changeStatus(@RequestBody @Validated ChangeStatusDTO statusDTO) {
        houseService.changeStatus(statusDTO.getHouseId(), statusDTO.getStatus());
        return R.ok();
    }

    /**
     * 获取热门房源列表
     */
    @GetMapping("/hot")
    public R<Page<HouseListVO>> getHotHouses(@RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize) {
        Page<HouseListVO> page = new Page<>(pageNum, pageSize);
        return R.ok(houseService.selectHotHouseDetailPage(page));
    }

    /**
     * 获取最新房源列表
     */
    @GetMapping("/latest")
    public R<Page<HouseListVO>> getLatestHouses(@RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize) {
        Page<HouseListVO> page = new Page<>(pageNum, pageSize);
        return R.ok(houseService.selectLatestHouseDetailPage(page));
    }

    /**
     * 查询附近房源
     */
    @GetMapping("/nearby")
    public R<Page<HouseMapVO>> getNearbyHouses(
            @RequestParam Double lng,
            @RequestParam Double lat,
            @RequestParam(defaultValue = "10000") Double radius,
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize) {
        log.info("查询附近房源，经度:{}, 纬度:{}, 半径:{}米", lng, lat, radius);
        Page<HouseMapVO> page = new Page<>(pageNum, pageSize);
        return R.ok(houseService.selectNearbyHouses(lng, lat, radius, page));
    }

    /**
     * 验证经纬度范围
     */
    private void validateCoordinate(BigDecimal lng, BigDecimal lat) {
        // 经度范围：-180到180
        if (lng.compareTo(new BigDecimal("-180")) < 0 || lng.compareTo(new BigDecimal("180")) > 0) {
            throw new ServiceException("经度范围无效，应在-180到180之间");
        }
        
        // 纬度范围：-90到90
        if (lat.compareTo(new BigDecimal("-90")) < 0 || lat.compareTo(new BigDecimal("90")) > 0) {
            throw new ServiceException("纬度范围无效，应在-90到90之间");
        }
    }

    /**
     * 更新所有房源的封面图片
     * 将所有没有封面图片的房源设置第一张图片为封面图片
     */
    @PutMapping("/updateAllCoverImages")
    @SaCheckRole("admin")  // 需要管理员权限
    public R<Void> updateAllCoverImages() {
        log.info("开始更新所有房源的封面图片");
        houseService.updateAllHouseCoverImages();
        return R.ok();
    }

    /**
     * 批量更新所有房源的经纬度
     * 针对历史数据批量处理，将没有经纬度的房源根据地址获取经纬度
     */
    @PutMapping("/updateAllCoordinates")
    @SaCheckRole("admin")  // 需要管理员权限
    public R<Map<String, Object>> updateAllCoordinates() {
        log.info("开始批量更新所有房源的经纬度");
        
        // 查询所有缺少经纬度的房源
        List<HouseInfo> houses = houseService.lambdaQuery()
                .isNull(HouseInfo::getLng)
                .or()
                .isNull(HouseInfo::getLat)
                .or()
                .eq(HouseInfo::getLng, 0)
                .or()
                .eq(HouseInfo::getLat, 0)
                .list();
        
        log.info("找到 {} 个缺少经纬度的房源", houses.size());
        
        int successCount = 0;
        int failCount = 0;
        
        for (HouseInfo house : houses) {
            try {
                // 构建完整地址
                String fullAddress = house.getProvince() + house.getCity() + 
                                     house.getDistrict() + house.getAddress();
                
                // 对于地址字段不完整的房源，跳过
                if (fullAddress.trim().length() < 5) {
                    log.warn("房源ID {}的地址不完整，跳过：{}", house.getHouseId(), fullAddress);
                    failCount++;
                    continue;
                }
                
                log.info("房源ID {}开始获取经纬度，地址: {}", house.getHouseId(), fullAddress);
                Coordinate coordinate = mapService.geocoder(fullAddress);
                
                if (coordinate != null) {
                    house.setLng(coordinate.getLng());
                    house.setLat(coordinate.getLat());
                    house.setUpdateTime(LocalDateTime.now());
                    house.setUpdateBy(StpUtil.getLoginIdAsString());
                    
                    boolean updated = houseService.updateById(house);
                    if (updated) {
                        log.info("房源ID {}经纬度更新成功: {}, {}", 
                                house.getHouseId(), coordinate.getLng(), coordinate.getLat());
                        successCount++;
                    } else {
                        log.error("房源ID {}经纬度更新失败", house.getHouseId());
                        failCount++;
                    }
                } else {
                    log.warn("房源ID {}无法获取经纬度", house.getHouseId());
                    failCount++;
                }
                
                // 为避免API调用过快，增加延迟
                Thread.sleep(200);
            } catch (Exception e) {
                log.error("处理房源ID " + house.getHouseId() + " 时出错", e);
                failCount++;
            }
        }
        
        Map<String, Object> result = new HashMap<>();
        result.put("total", houses.size());
        result.put("success", successCount);
        result.put("fail", failCount);
        
        log.info("批量更新房源经纬度完成：总数={}, 成功={}, 失败={}", 
                houses.size(), successCount, failCount);
        
        return R.ok(result);
    }
}
